package com.example.smartwaterapi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.smartwaterapi.common.api.ResultCode;
import com.example.smartwaterapi.common.exception.ApiException;
import com.example.smartwaterapi.entity.User;
import com.example.smartwaterapi.security.JwtTokenUtil;
import com.example.smartwaterapi.security.SecurityUser;
import com.example.smartwaterapi.service.UserService;
import com.example.smartwaterapi.service.WechatService;
import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.Date;

/**
 * 微信服务实现
 */
@Slf4j
@Service
public class WechatServiceImpl implements WechatService {

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private UserService userService;
    
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    
    @Autowired
    private RestTemplate restTemplate;

    @Value("${wechat.official.appid:}")
    private String officialAccountAppId;

    @Value("${wechat.official.secret:}")
    private String officialAccountAppSecret;

    /**
     * 微信小程序登录
     */
    @Override
    public Map<String, Object> login(String code) {
        try {
            if (!StringUtils.hasText(code)) {
                log.error("微信登录失败: code参数为空");
                throw new ApiException(ResultCode.WECHAT_CODE_INVALID);
            }
            
            log.info("开始微信登录流程, code: {}", code);
            
            // 检查code是否已被使用
            User existingUser = userService.getRecentLoginUserByCode(code);
            if (existingUser != null && existingUser.getId() != null) {
                log.info("检测到code已被使用，尝试直接返回已登录用户: userId={}, nickname={}", existingUser.getId(), existingUser.getNickname());
                userService.updateLastLogin(existingUser.getId(), code);
                return generateLoginResponse(existingUser, code);
            }
            
            try {
                // 获取微信session
                WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
                if (session == null) {
                    log.error("微信登录失败: session为空");
                    throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED);
                }
                
                String openid = session.getOpenid();
                String unionid = session.getUnionid();
                String sessionKey = session.getSessionKey();
                
                if (openid == null || openid.isEmpty()) {
                    log.error("微信登录失败: openid为空");
                    throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED);
                }
                
                log.info("微信登录session获取成功: openid={}, unionid={}", openid, unionid);
                
                // 尝试直接通过openid获取用户ID
                Long directUserId = userService.getUserIdByOpenid(openid);
                User user = null;
                
                if (directUserId != null) {
                    // 如果能直接获取到用户ID，优先使用
                    log.info("通过openid直接查询到用户ID: {}", directUserId);
                    user = userService.getById(directUserId);
                    
                    // 输出所有用户信息便于调试
                    if (user != null) {
                        log.info("查询到用户详细信息: id={}, openid={}, nickname={}, avatar={}", 
                               user.getId(), user.getOpenid(), user.getNickname(), user.getAvatar());
                    } else {
                        log.error("严重错误: 使用ID={}查询后用户为null", directUserId);
                    }
                    
                    // 更新session_key
                    if (user != null && !sessionKey.equals(user.getSessionKey())) {
                        User updateUser = new User();
                        updateUser.setId(directUserId);
                        updateUser.setSessionKey(sessionKey);
                        updateUser.setUpdatedAt(LocalDateTime.now());
                        userService.updateById(updateUser);
                    }
                }
                
                // 如果直接查询失败，尝试获取或创建用户
                if (user == null) {
                    user = getOrCreateWechatUser(openid, unionid, sessionKey);
                }
                
                // 确保用户对象有效并且ID不为null
                if (user == null) {
                    log.error("微信登录失败: 用户对象为null");
                    throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED);
                }
                
                // 重要：强制修复用户ID问题
                if (user.getId() == null) {
                    log.error("用户ID为null，但openid存在: {}", user.getOpenid());
                    
                    // 直接使用查询到的用户ID
                    Long userId = directUserId;
                    
                    // 如果directUserId不存在，重新查询
                    if (userId == null && user.getOpenid() != null) {
                        userId = userService.getUserIdByOpenid(user.getOpenid());
                    }
                    
                    if (userId != null) {
                        log.info("强制设置用户ID: {}", userId);
                        user.setId(userId);
                    } else {
                        log.error("无法获取有效的用户ID，openid: {}", user.getOpenid());
                        throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "无法获取有效的用户ID");
                    }
                }
                
                log.info("微信登录成功: userId={}, nickname={}, id存在={}", user.getId(), user.getNickname(), (user.getId() != null));
                
                // 更新用户最后登录信息
                log.info("更新用户最后登录信息: userId={}", user.getId());
                userService.updateLastLogin(user.getId(), code);
                
                // 生成登录响应数据
                return generateLoginResponse(user, code);
            } catch (WxErrorException e) {
                log.error("微信登录请求异常: {}", e.getMessage(), e);
                throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "微信登录失败: " + e.getMessage());
            }
        } catch (ApiException e) {
            log.error("微信登录异常: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("微信登录异常: ", e);
            throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED);
        }
    }
    
    /**
     * 生成登录响应数据
     */
    private Map<String, Object> generateLoginResponse(User user, String code) {
        // 确保用户对象有效
        if (user == null) {
            log.error("生成登录响应失败: 用户对象为null");
            throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED);
        }
        
        // 🎯 统一修复用户ID
        user = fixUserIdIfNeeded(user, user.getOpenid(), "openid");
        
        // 最终检查确保用户ID有效
        if (user.getId() == null) {
            log.error("生成登录响应失败: 用户ID仍为null, openid={}", user.getOpenid());
            throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "无法获取有效用户ID");
        }
        
        Map<String, Object> response = new HashMap<>();
        
        // 明确设置用户ID为字符串类型，避免前端解析问题
        response.put("userId", String.valueOf(user.getId()));
        response.put("nickname", user.getNickname() != null ? user.getNickname() : "微信用户");
        response.put("avatar", user.getAvatar());
        response.put("gender", user.getGender() != null ? user.getGender() : 0);
        
        try {
            // 生成JWT令牌
            String token = generateToken(user);
            response.put("token", token);
        } catch (Exception e) {
            log.error("生成令牌失败: {}", e.getMessage());
            throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "生成登录令牌失败");
        }
        
        // 添加更多用户信息
        response.put("uuid", user.getUuid());
        response.put("openid", user.getOpenid());
        response.put("unionid", user.getUnionid());
        
        // 添加时间戳
        response.put("loginTime", new Date().getTime());
        
        log.info("生成微信登录响应成功: userId={}, nickname={}", user.getId(), user.getNickname());
        return response;
    }

    /**
     * 微信小程序登录并绑定手机号
     */
    @Override
    public Map<String, Object> loginWithPhone(String code, String encryptedData, String iv) {
        try {
            if (!StringUtils.hasText(code)) {
                log.error("微信手机号登录失败: code参数为空");
                throw new ApiException(ResultCode.WECHAT_CODE_INVALID);
            }

            log.info("开始微信手机号登录流程, code: {}", code);
            
            try {
            // 获取微信登录session
            WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
                if (session == null) {
                    log.error("微信手机号登录失败: session为空");
                    throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED);
                }
                
            String openid = session.getOpenid();
            String unionid = session.getUnionid();
            String sessionKey = session.getSessionKey();

                if (openid == null || openid.isEmpty()) {
                    log.error("微信手机号登录失败: openid为空");
                    throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED);
                }
                
                log.info("微信手机号登录session获取成功: openid={}, unionid={}", openid, unionid);

                try {
            // 解密手机号
            WxMaPhoneNumberInfo phoneNumberInfo = wxMaService.getUserService().getPhoneNoInfo(sessionKey, encryptedData, iv);
            String phoneNumber = phoneNumberInfo.getPhoneNumber();
                    log.info("成功解密获取手机号: {}", phoneNumber);

            // 查找手机号对应的用户
            User existingUser = userService.getByPhone(phoneNumber);
            if (existingUser != null) {
                        log.info("找到手机号对应的用户: userId={}, nickname={}", existingUser.getId(), existingUser.getNickname());
                        
                        // 🎯 重要修复：确保用户ID正确设置
                        existingUser = fixUserIdIfNeeded(existingUser, phoneNumber, "phone");
                        
                        // 检查并修复用户ID问题
                        if (existingUser.getId() == null) {
                            log.error("生成登录响应失败: 用户ID为null, openid={}", openid);
                            // 尝试通过openid查询用户ID
                            Long userId = userService.getUserIdByOpenid(openid);
                            if (userId != null) {
                                log.info("通过openid修复用户ID: {}", userId);
                                existingUser.setId(userId);
                            } else {
                                log.error("无法修复用户ID，尝试通过手机号查询");
                                // 可能是数据库中的用户记录缺少openid，需要特殊处理
                                boolean updateResult = userService.updateUserByPhone(phoneNumber, openid, unionid, sessionKey);
                                if (updateResult) {
                                    // 重新查询更新后的用户
                                    existingUser = userService.getByPhone(phoneNumber);
                                    existingUser = fixUserIdIfNeeded(existingUser, phoneNumber, "phone");
                                    log.info("通过手机号更新用户成功，重新查询: userId={}", existingUser != null ? existingUser.getId() : "null");
                                } else {
                                    log.error("通过手机号更新用户失败");
                                    throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "用户信息更新失败");
                                }
                            }
                        }
                        
                // 更新微信信息，确保unionid和其他字段都被保存
                existingUser.setOpenid(openid);
                existingUser.setUnionid(unionid);
                existingUser.setSessionKey(sessionKey);
                existingUser.setUpdatedAt(LocalDateTime.now());
                        existingUser.setLastLoginTime(LocalDateTime.now());
                
                log.info("准备更新用户信息: userId={}, openid={}, unionid={}", 
                        existingUser.getId(), openid, unionid);
                
                boolean updateResult = userService.updateById(existingUser);
                if (!updateResult) {
                    log.error("用户信息更新失败，userId={}", existingUser.getId());
                    throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "用户信息更新失败");
                }
                log.info("已更新用户微信信息: userId={}, openid={}, unionid={}", 
                        existingUser.getId(), openid, unionid);
                
                // 重新从数据库获取最新用户信息确保数据正确
                User freshUser = userService.getById(existingUser.getId());
                if (freshUser != null) {
                    freshUser = fixUserIdIfNeeded(freshUser, String.valueOf(existingUser.getId()), "id");
                    existingUser = freshUser;
                    log.info("重新获取用户信息: unionid={}", existingUser.getUnionid());
                }
                
                // 返回登录结果
                        return generateLoginResponse(existingUser, code);
            } else {
                        log.info("未找到手机号对应用户，创建新用户");
                // 获取或创建微信用户，并绑定手机号
                User user = getOrCreateWechatUser(openid, unionid, sessionKey);
                        
                        // 确保用户对象有效
                        if (user == null) {
                            log.error("获取或创建微信用户失败");
                            throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED);
                        }
                        
                        // 🎯 重要修复：确保新创建用户的ID正确设置
                        user = fixUserIdIfNeeded(user, openid, "openid");
                        
                        // 检查用户ID是否为null，如果是则尝试修复
                        if (user.getId() == null) {
                            log.error("微信用户ID为null: openid={}, nickname={}", user.getOpenid(), user.getNickname());
                            Long userId = userService.getUserIdByOpenid(openid);
                            if (userId != null) {
                                log.info("通过openid直接查询到用户ID: {}", userId);
                                // 重新获取完整用户信息
                                User completeUser = userService.getById(userId);
                                if (completeUser != null) {
                                    completeUser = fixUserIdIfNeeded(completeUser, String.valueOf(userId), "id");
                                    user = completeUser;
                                    log.info("通过ID直接查询到完整用户: {}", userId);
                                } else {
                                    user.setId(userId);
                                    log.info("成功修复用户ID: {}", userId);
                                }
                            } else {
                                log.error("用户ID修复失败，仍然为null");
                                throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "用户ID为null，无法更新");
                            }
                        }
                        
                        // 再次检查用户ID，确保不为null
                        if (user.getId() == null) {
                            log.error("用户ID修复失败，仍然为null");
                            throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "用户ID为null，无法更新");
                        }
                        
                        // 绑定手机号并更新，确保unionid也被保存
                        user.setPhone(phoneNumber);
                        user.setUnionid(unionid);  // 确保unionid被保存
                        user.setLastLoginTime(LocalDateTime.now());
                        user.setUpdatedAt(LocalDateTime.now());
                        
                log.info("准备更新新用户信息: userId={}, phone={}, unionid={}", 
                        user.getId(), phoneNumber, unionid);
                        
                boolean updateResult = userService.updateById(user);
                if (!updateResult) {
                    log.error("新用户信息更新失败，userId={}", user.getId());
                    throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "用户信息更新失败");
                }
                        log.info("已绑定手机号并更新用户: userId={}", user.getId());
                
                // 重新从数据库获取最新用户信息确保数据正确
                User freshUser = userService.getById(user.getId());
                if (freshUser != null) {
                    freshUser = fixUserIdIfNeeded(freshUser, String.valueOf(user.getId()), "id");
                    user = freshUser;
                    log.info("重新获取新用户信息: unionid={}", user.getUnionid());
                }
                
                // 返回登录结果
                        return generateLoginResponse(user, code);
                    }
                } catch (Exception e) {
                    log.error("微信手机号解密或处理失败: {}", e.getMessage(), e);
                    throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "手机号获取失败");
                }
            } catch (WxErrorException e) {
                log.error("微信登录请求异常: {}", e.getMessage(), e);
                throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "微信登录失败: " + e.getMessage());
            }
        } catch (ApiException e) {
            log.error("微信手机号登录异常: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("微信手机号登录异常: ", e);
            throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED);
        }
    }

    /**
     * 更新用户微信信息
     */
    @Override
    public boolean updateUserInfo(Long userId, String nickname, String avatar, Integer gender) {
        User user = userService.getById(userId);
        if (user == null) {
            throw new ApiException(ResultCode.USER_NOT_FOUND);
        }

        // 更新用户信息
        if (StringUtils.hasText(nickname)) {
            user.setNickname(nickname);
        }
        if (StringUtils.hasText(avatar)) {
            user.setAvatar(avatar);
        }
        if (gender != null) {
            user.setGender(gender);
        }
        user.setUpdatedAt(LocalDateTime.now());

        return userService.updateById(user);
    }

    /**
     * 绑定微信账号
     */
    @Override
    public boolean bindWechat(Long userId, String code) {
        try {
            // 检查参数
            if (userId == null || !StringUtils.hasText(code)) {
                log.error("绑定微信参数无效: userId={}, code={}", userId, code);
                throw new ApiException(ResultCode.VALIDATE_FAILED, "参数无效");
            }
            
            // 查询用户
            User user = userService.getById(userId);
            if (user == null) {
                log.error("绑定微信失败: 用户不存在, userId={}", userId);
                throw new ApiException(ResultCode.USER_NOT_FOUND, "用户不存在");
            }
            
            try {
                // 获取微信登录session
                WxMaJscode2SessionResult session = wxMaService.getUserService().getSessionInfo(code);
                String openid = session.getOpenid();
                String unionid = session.getUnionid();
                String sessionKey = session.getSessionKey();
                
                // 检查是否已绑定
                if (StringUtils.hasText(user.getOpenid())) {
                    log.warn("用户已绑定微信: userId={}, openid={}", userId, user.getOpenid());
                    return true;
                }
                
                // 检查openid是否已被其他用户绑定
                User existingUser = userService.getByOpenid(openid);
                if (existingUser != null && !existingUser.getId().equals(userId)) {
                    log.error("绑定微信失败: openid已被其他用户绑定, openid={}, existingUserId={}", openid, existingUser.getId());
                    throw new ApiException(ResultCode.VALIDATE_FAILED, "该微信账号已被其他用户绑定");
                }
                
                // 更新用户信息
                User updateUser = new User();
                updateUser.setId(userId);
                updateUser.setOpenid(openid);
                updateUser.setUnionid(unionid);
                updateUser.setSessionKey(sessionKey);
                updateUser.setUpdatedAt(LocalDateTime.now());
                
                boolean result = userService.updateById(updateUser);
                log.info("绑定微信{}: userId={}, openid={}", result ? "成功" : "失败", userId, openid);
                
                return result;
            } catch (WxErrorException e) {
                log.error("获取微信session失败", e);
                throw new ApiException(ResultCode.FAILED, "获取微信信息失败");
            }
        } catch (ApiException e) {
            throw e;
        } catch (Exception e) {
            log.error("绑定微信异常", e);
            throw new ApiException(ResultCode.FAILED, "绑定微信失败");
        }
    }
    
    /**
     * 解绑微信
     */
    @Override
    public boolean unbindWechat(Long userId) {
        try {
            // 检查参数
            if (userId == null) {
                throw new ApiException(ResultCode.VALIDATE_FAILED, "参数无效");
            }
            
            // 查询用户
            User user = userService.getById(userId);
            if (user == null) {
                throw new ApiException(ResultCode.USER_NOT_FOUND, "用户不存在");
            }
            
            // 检查是否已绑定
            if (!StringUtils.hasText(user.getOpenid())) {
                log.warn("用户未绑定微信: userId={}", userId);
                return true;
            }
            
            // 更新用户信息
            User updateUser = new User();
            updateUser.setId(userId);
            updateUser.setOpenid(null);
            updateUser.setUnionid(null);
            updateUser.setUpdatedAt(LocalDateTime.now());
            
            boolean result = userService.updateById(updateUser);
            log.info("解绑微信{}: userId={}", result ? "成功" : "失败", userId);
            
            return result;
        } catch (ApiException e) {
            throw e;
        } catch (Exception e) {
            log.error("解绑微信异常", e);
            throw new ApiException(ResultCode.FAILED, "解绑微信失败");
        }
    }

    /**
     * 获取或创建微信用户
     */
    @Override
    @Transactional
    public User getOrCreateWechatUser(String openid, String unionid, String sessionKey) {
        log.info("微信登录: openid={}, unionid={}", openid, unionid);
        
        try {
            // 首先通过openid直接查询用户ID，以确保有有效ID
            Long userId = userService.getUserIdByOpenid(openid);
            
            // 如果能直接获取到用户ID，先尝试直接查询完整用户
            if (userId != null) {
                log.info("通过openid直接查询到用户ID: {}", userId);
                User user = userService.getById(userId);
                if (user != null) {
                    log.info("通过ID直接查询到完整用户: {}", userId);
                    
                    // 🎯 修复用户ID
                    user = fixUserIdIfNeeded(user, String.valueOf(userId), "id");
                    
                    // 确保session_key和unionid为最新
                    boolean needUpdate = false;
                    if (!sessionKey.equals(user.getSessionKey())) {
                        user.setSessionKey(sessionKey);
                        needUpdate = true;
                    }
                    if (unionid != null && !unionid.equals(user.getUnionid())) {
                        user.setUnionid(unionid);
                        needUpdate = true;
                        log.info("更新用户unionid: {}", unionid);
                    }
                    if (needUpdate) {
                        // 确保用户对象有正确的ID
                        if (user.getId() == null) {
                            user.setId(userId);
                            log.info("设置用户ID: {}", userId);
                        }
                        boolean updateResult = userService.updateById(user);
                        log.info("已更新用户信息: userId={}, unionid={}, 更新结果={}", userId, unionid, updateResult);
                    }
                    return user;
                }
            }
            
            // 如果直接查询ID失败，使用标准方法创建或更新用户
            User user = userService.createOrUpdateWechatUser(openid, sessionKey, "微信用户", null, 0);
            
            // 检查用户是否为null
            if (user == null) {
                log.error("获取或创建微信用户失败: openid={}", openid);
                throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "获取用户信息失败");
            }
            
            // 🎯 修复用户ID
            user = fixUserIdIfNeeded(user, openid, "openid");
            
            // 确保unionid被设置
            if (unionid != null && !unionid.equals(user.getUnionid())) {
                user.setUnionid(unionid);
                boolean updateResult = userService.updateById(user);
                log.info("设置用户unionid: userId={}, unionid={}, 更新结果={}", user.getId(), unionid, updateResult);
            }
            
            // 最终检查用户ID有效性
            if (user.getId() == null) {
                log.error("所有修复尝试失败，无法获取有效用户ID: openid={}", openid);
                throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "无法获取有效用户ID");
            }
            
            log.info("用户ID检查通过: {}", user.getId());
            return user;
        } catch (ApiException e) {
            log.error("获取或创建微信用户异常: {}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("获取或创建微信用户异常", e);
            throw new ApiException(ResultCode.WECHAT_LOGIN_FAILED, "获取或创建用户失败");
        }
    }
    
    /**
     * 生成用户令牌
     * 使用JWT令牌
     */
    private String generateToken(User user) {
        if (user == null) {
            log.error("无法生成令牌，用户对象为null");
            throw new ApiException(ResultCode.FAILED, "无法生成用户令牌");
        }
        
        if (user.getId() == null) {
            log.error("无法生成令牌，用户ID为null, openid={}", user.getOpenid());
            
            // 尝试通过openid查询用户ID
            if (user.getOpenid() != null) {
                Long userId = userService.getUserIdByOpenid(user.getOpenid());
                if (userId != null) {
                    log.info("通过openid查询到用户ID: {}，继续生成令牌", userId);
                    user.setId(userId);
                } else {
                    throw new ApiException(ResultCode.FAILED, "用户ID无效");
                }
            } else {
                throw new ApiException(ResultCode.FAILED, "无法生成用户令牌: 用户ID和openid均为空");
            }
        }
        
        // 使用JwtTokenUtil生成JWT令牌
        SecurityUser securityUser = new SecurityUser(user);
        
        // 添加额外安全检查，确保用户ID一定有效
        if (securityUser.getUserId() == null) {
            log.error("SecurityUser中的getUserId返回null，即使已设置user.id={}", user.getId());
            throw new ApiException(ResultCode.FAILED, "无法生成用户令牌");
        }
        
        // 打印用户ID和openid，确保数据正确
        log.debug("生成令牌 - 用户ID: {}, openid: {}", securityUser.getUserId(), user.getOpenid());
        
        // 创建自定义claims
        Map<String, Object> claims = new HashMap<>();
        claims.put("username", user.getOpenid()); // 使用openid作为username
        
        // 使用用户ID作为subject
        String userId = String.valueOf(user.getId());
        return jwtTokenUtil.generateToken(userId, claims);
    }
    
    /**
     * 创建新用户(内部方法，用于修复ID为null的情况)
     */
    private User createNewUser(String openid, String sessionKey, String nickname, String avatar, Integer gender) {
        log.info("手动创建新微信用户: openid={}, nickname={}", openid, nickname);
        
        User user = new User();
        // 生成随机UUID作为用户唯一标识
        user.setUuid(UUID.randomUUID().toString().replace("-", ""));
        user.setOpenid(openid);
        user.setSessionKey(sessionKey);
        user.setNickname(nickname);
        user.setAvatar(avatar);
        user.setGender(gender);
        user.setDailyGoal(2000); // 默认饮水目标
                    user.setReminderEnabled(0); // 🔕 默认关闭提醒，避免打扰用户
        user.setReminderInterval(60); // 默认提醒间隔
        user.setMembershipLevel("basic"); // 默认会员等级
        user.setPoints(0);
        user.setTotalPoints(0);
        user.setStatus(1); // 正常状态
        user.setCreatedAt(LocalDateTime.now());
        user.setUpdatedAt(LocalDateTime.now());
        user.setLastLoginTime(LocalDateTime.now()); // 设置首次登录时间
        
        // 使用新方法创建用户并确保获取ID
        user = userService.createUserAndGetId(user);
        
        if (user != null) {
            log.info("手动创建用户成功: userId={}", user.getId());
            
            // 二次确认，如果ID仍为null
            if (user.getId() == null && user.getOpenid() != null) {
                // 最后尝试直接查询
                Long userId = userService.getUserIdByOpenid(user.getOpenid());
                if (userId != null) {
                    log.info("通过查询获取新用户ID: {}", userId);
                    user.setId(userId);
                }
            }
        } else {
            log.error("创建用户失败: openid={}", openid);
        }
        
        return user;
    }

    /**
     * 通过授权码获取公众号用户信息
     */
    @Override
    public WechatOfficialUserInfo getOfficialAccountUserInfo(String authCode) {
        try {
            log.info("🔑 开始通过授权码获取公众号用户信息: authCode={}", authCode);
            
            if (!StringUtils.hasText(authCode)) {
                log.error("❌ 授权码为空");
                return null;
            }
            
            // Step 1: 通过授权码获取access_token
            String tokenUrl = String.format(
                "https://api.weixin.qq.com/sns/oauth2/access_token?" +
                "appid=%s&secret=%s&code=%s&grant_type=authorization_code",
                getOfficialAccountAppId(),
                getOfficialAccountAppSecret(),
                authCode
            );
            
            log.info("📝 请求access_token: {}", tokenUrl.replaceAll("secret=[^&]+", "secret=***"));
            
            // 使用RestTemplate发送请求
            String tokenResponse = restTemplate.getForObject(tokenUrl, String.class);
            log.info("📥 Token响应: {}", tokenResponse);
            
            if (!StringUtils.hasText(tokenResponse)) {
                log.error("❌ 获取access_token失败: 响应为空");
                return null;
            }
            
            // 解析token响应
            Map<String, Object> tokenMap = parseJsonResponse(tokenResponse);
            if (tokenMap.containsKey("errcode")) {
                log.error("❌ 获取access_token失败: {}", tokenMap);
                return null;
            }
            
            String accessToken = (String) tokenMap.get("access_token");
            String openid = (String) tokenMap.get("openid");
            
            if (!StringUtils.hasText(accessToken) || !StringUtils.hasText(openid)) {
                log.error("❌ access_token或openid为空: accessToken={}, openid={}", accessToken, openid);
                return null;
            }
            
            log.info("✅ 获取到access_token: openid={}", openid);
            
            // Step 2: 通过access_token获取用户信息
            String userInfoUrl = String.format(
                "https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN",
                accessToken, openid
            );
            
            log.info("📝 请求用户信息: {}", userInfoUrl.replaceAll("access_token=[^&]+", "access_token=***"));
            
            String userResponse = restTemplate.getForObject(userInfoUrl, String.class);
            log.info("📥 用户信息响应: {}", userResponse);
            
            if (!StringUtils.hasText(userResponse)) {
                log.error("❌ 获取用户信息失败: 响应为空");
                return null;
            }
            
            // 解析用户信息响应
            Map<String, Object> userMap = parseJsonResponse(userResponse);
            if (userMap.containsKey("errcode")) {
                log.error("❌ 获取用户信息失败: {}", userMap);
                return null;
            }
            
            // 构建返回对象
            WechatOfficialUserInfo userInfo = new WechatOfficialUserInfo();
            userInfo.setOpenid((String) userMap.get("openid"));
            userInfo.setNickname((String) userMap.get("nickname"));
            userInfo.setHeadimgurl((String) userMap.get("headimgurl"));
            userInfo.setUnionid((String) userMap.get("unionid"));
            userInfo.setSex((Integer) userMap.get("sex"));
            
            log.info("✅ 成功获取公众号用户信息: openid={}, nickname={}, unionid={}", 
                userInfo.getOpenid(), userInfo.getNickname(), userInfo.getUnionid());
            
            return userInfo;
            
        } catch (Exception e) {
            log.error("❌ 获取公众号用户信息异常", e);
            return null;
        }
    }
    
    /**
     * 解析JSON响应
     */
    private Map<String, Object> parseJsonResponse(String response) {
        try {
            // 这里简化处理，实际项目中建议使用Jackson或其他JSON库
            if (response.contains("\"errcode\"")) {
                // 错误响应
                Map<String, Object> errorMap = new HashMap<>();
                if (response.contains("40029")) {
                    errorMap.put("errcode", 40029);
                    errorMap.put("errmsg", "invalid code");
                } else if (response.contains("40013")) {
                    errorMap.put("errcode", 40013);
                    errorMap.put("errmsg", "invalid appid");
                }
                return errorMap;
            }
            
            // 成功响应 - 简单解析
            Map<String, Object> result = new HashMap<>();
            
            // 提取access_token
            if (response.contains("access_token")) {
                String accessToken = extractJsonValue(response, "access_token");
                result.put("access_token", accessToken);
            }
            
            // 提取openid
            if (response.contains("openid")) {
                String openid = extractJsonValue(response, "openid");
                result.put("openid", openid);
            }
            
            // 提取用户信息
            if (response.contains("nickname")) {
                result.put("nickname", extractJsonValue(response, "nickname"));
                result.put("headimgurl", extractJsonValue(response, "headimgurl"));
                result.put("unionid", extractJsonValue(response, "unionid"));
                
                // 提取性别
                String sexStr = extractJsonValue(response, "sex");
                if (StringUtils.hasText(sexStr)) {
                    try {
                        result.put("sex", Integer.parseInt(sexStr));
                    } catch (NumberFormatException e) {
                        result.put("sex", 0);
                    }
                }
            }
            
            return result;
            
        } catch (Exception e) {
            log.error("❌ 解析JSON响应失败", e);
            return new HashMap<>();
        }
    }
    
    /**
     * 从JSON字符串中提取指定字段的值
     */
    private String extractJsonValue(String json, String key) {
        try {
            String pattern = "\"" + key + "\":\"";
            int startIndex = json.indexOf(pattern);
            if (startIndex == -1) {
                // 尝试数字类型
                pattern = "\"" + key + "\":";
                startIndex = json.indexOf(pattern);
                if (startIndex == -1) {
                    return null;
                }
                startIndex += pattern.length();
                int endIndex = json.indexOf(",", startIndex);
                if (endIndex == -1) {
                    endIndex = json.indexOf("}", startIndex);
                }
                if (endIndex == -1) {
                    return null;
                }
                return json.substring(startIndex, endIndex).trim();
            } else {
                startIndex += pattern.length();
                int endIndex = json.indexOf("\"", startIndex);
                if (endIndex == -1) {
                    return null;
                }
                return json.substring(startIndex, endIndex);
            }
        } catch (Exception e) {
            log.error("❌ 提取JSON值失败: key={}", key, e);
            return null;
        }
    }
    
    /**
     * 获取公众号AppId
     */
    private String getOfficialAccountAppId() {
        return officialAccountAppId;
    }
    
    /**
     * 获取公众号AppSecret
     */
    private String getOfficialAccountAppSecret() {
        return officialAccountAppSecret;
    }

    /**
     * 绑定公众号到用户
     */
    @Override
    public boolean bindOfficialAccountToUser(Long userId, String officialAccountOpenid) {
        try {
            if (userId == null || !StringUtils.hasText(officialAccountOpenid)) {
                log.error("绑定公众号失败: 参数无效 - userId={}, officialAccountOpenid={}", userId, officialAccountOpenid);
                return false;
            }

            log.info("开始绑定公众号到用户: userId={}, officialAccountOpenid={}", userId, officialAccountOpenid);

            // 获取用户信息
            User user = userService.getById(userId);
            if (user == null) {
                log.error("绑定公众号失败: 用户不存在 - userId={}", userId);
                return false;
            }

            // 🎯 关键修复：确保user对象的ID正确设置
            if (user.getId() == null) {
                log.warn("用户对象ID为null，强制设置为参数userId: {}", userId);
                user.setId(userId);
            }

            // 检查是否已经绑定过这个公众号openid
            if (StringUtils.hasText(user.getWxOpenid()) && user.getWxOpenid().equals(officialAccountOpenid)) {
                log.info("用户已绑定此公众号openid，无需重复绑定: userId={}, officialAccountOpenid={}", userId, officialAccountOpenid);
                return true;
            }

            // 检查这个公众号openid是否被其他用户使用
            User existingUser = userService.getByWxOpenid(officialAccountOpenid);
            if (existingUser != null && !existingUser.getId().equals(userId)) {
                log.warn("公众号openid已被其他用户使用: officialAccountOpenid={}, existingUserId={}", 
                        officialAccountOpenid, existingUser.getId());
                // 这里可以选择处理策略：
                // 1. 直接返回false
                // 2. 解绑原用户并绑定到新用户
                // 目前选择策略1，保持数据完整性
                return false;
            }

            // 🎯 使用更直接的方式更新数据库，避免对象ID问题
            log.info("直接更新数据库，设置用户{}的wx_openid为: {}", userId, officialAccountOpenid);
            boolean updateResult = userService.updateWxOpenid(userId, officialAccountOpenid);
            
            if (updateResult) {
                log.info("公众号绑定成功: userId={}, officialAccountOpenid={}", userId, officialAccountOpenid);
                return true;
            } else {
                log.error("公众号绑定失败: 数据库更新失败 - userId={}", userId);
                return false;
            }

        } catch (Exception e) {
            log.error("绑定公众号异常: userId={}, officialAccountOpenid={}", userId, officialAccountOpenid, e);
            return false;
        }
    }

    /**
     * 修复用户ID问题 - 确保User对象的ID字段正确设置
     * 这是一个临时解决方案，用于处理MyBatis映射可能导致的ID为null问题
     */
    private User fixUserIdIfNeeded(User user, String identifier, String identifierType) {
        if (user == null) {
            return null;
        }
        
        if (user.getId() == null) {
            log.warn("用户对象ID为null，尝试修复 - {}: {}", identifierType, identifier);
            
            Long userId = null;
            try {
                // 根据不同标识符类型查询用户ID
                switch (identifierType.toLowerCase()) {
                    case "openid":
                        userId = userService.getUserIdByOpenid(identifier);
                        break;
                    case "phone":
                        User phoneUser = userService.getByPhone(identifier);
                        if (phoneUser != null && phoneUser.getId() != null) {
                            userId = phoneUser.getId();
                        } else if (phoneUser != null) {
                            // 如果通过手机号查询的用户ID也为null，尝试数据库直接查询
                            userId = userService.getUserIdByOpenid(phoneUser.getOpenid());
                        }
                        break;
                    case "id":
                        // 如果是通过ID查询但ID字段为null，直接使用查询的ID
                        try {
                            userId = Long.parseLong(identifier);
                        } catch (NumberFormatException e) {
                            log.error("无效的用户ID格式: {}", identifier);
                        }
                        break;
                    default:
                        log.warn("未知的标识符类型: {}", identifierType);
                }
                
                if (userId != null) {
                    log.info("修复用户ID成功: {} -> {}", identifierType, userId);
                    user.setId(userId);
                    
                    // 验证修复是否成功
                    if (user.getId() != null) {
                        log.info("用户ID修复验证成功: {}", user.getId());
                    } else {
                        log.error("用户ID修复验证失败，setId无效");
                    }
                } else {
                    log.error("无法通过{}修复用户ID: {}", identifierType, identifier);
                }
            } catch (Exception e) {
                log.error("修复用户ID过程中发生异常: {}", e.getMessage(), e);
            }
        }
        
        return user;
    }
} 